package org.jivesoftware.smackx.filetransfer;

import java.net.URLConnection;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import org.jivesoftware.smack.Connection;
import org.jivesoftware.smack.ConnectionListener;
import org.jivesoftware.smack.PacketCollector;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.filter.PacketIDFilter;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.IQ.Type;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.XMPPError;
import org.jivesoftware.smack.packet.XMPPError.Condition;
import org.jivesoftware.smackx.FormField;
import org.jivesoftware.smackx.FormField.Option;
import org.jivesoftware.smackx.ServiceDiscoveryManager;
import org.jivesoftware.smackx.packet.DataForm;
import org.jivesoftware.smackx.packet.StreamInitiation;
import org.jivesoftware.smackx.packet.StreamInitiation.File;

public class FileTransferNegotiator
{
  public static final String BYTE_STREAM = "http://jabber.org/protocol/bytestreams";
  public static boolean IBB_ONLY = 0;
  public static final String INBAND_BYTE_STREAM = "http://jabber.org/protocol/ibb";
  private static final String[] NAMESPACE;
  private static final String[] PROTOCOLS;
  protected static final String STREAM_DATA_FIELD_NAME = "stream-method";
  private static final String STREAM_INIT_PREFIX = "jsi_";
  private static final Random randomGenerator;
  private static final Map<Connection, FileTransferNegotiator> transferObject;
  private final Socks5TransferNegotiatorManager byteStreamTransferManager;
  private final Connection connection;
  private final StreamNegotiator inbandTransferManager;

  static
  {
    String[] arrayOfString1 = new String[4];
    arrayOfString1[0] = "http://jabber.org/protocol/si/profile/file-transfer";
    arrayOfString1[1] = "http://jabber.org/protocol/si";
    arrayOfString1[2] = "http://jabber.org/protocol/bytestreams";
    arrayOfString1[3] = "http://jabber.org/protocol/ibb";
    NAMESPACE = arrayOfString1;
    String[] arrayOfString2 = new String[2];
    arrayOfString2[0] = "http://jabber.org/protocol/bytestreams";
    arrayOfString2[1] = "http://jabber.org/protocol/ibb";
    PROTOCOLS = arrayOfString2;
    transferObject = new ConcurrentHashMap();
    randomGenerator = new Random();
    IBB_ONLY = false;
  }

  private FileTransferNegotiator(Connection paramConnection)
  {
    configureConnection(paramConnection);
    this.connection = paramConnection;
    this.byteStreamTransferManager = new Socks5TransferNegotiatorManager(paramConnection);
    this.inbandTransferManager = new IBBTransferNegotiator(paramConnection);
  }

  private void cleanup(Connection paramConnection)
  {
    if (transferObject.remove(paramConnection) != null)
    {
      this.byteStreamTransferManager.cleanup();
      this.inbandTransferManager.cleanup();
    }
  }

  private void configureConnection(Connection paramConnection)
  {
    paramConnection.addConnectionListener(new ConnectionListener(this, paramConnection)
    {
      public void connectionClosed()
      {
        FileTransferNegotiator.access$0(this.this$0, this.val$connection);
      }

      public void connectionClosedOnError()
      {
        FileTransferNegotiator.access$0(this.this$0, this.val$connection);
      }

      public void reconnectingIn()
      {
      }

      public void reconnectionFailed()
      {
      }

      public void reconnectionSuccessful()
      {
      }
    });
  }

  private DataForm createDefaultInitiationForm()
  {
    DataForm localDataForm = new DataForm("form");
    FormField localFormField = new FormField("stream-method");
    localFormField.setType("list-multi");
    if (!(IBB_ONLY))
      localFormField.addOption(new FormField.Option("http://jabber.org/protocol/bytestreams"));
    localFormField.addOption(new FormField.Option("http://jabber.org/protocol/ibb"));
    localDataForm.addField(localFormField);
    return localDataForm;
  }

  public static IQ createIQ(String paramString1, String paramString2, String paramString3, IQ.Type paramType)
  {
    1 local1 = new IQ()
    {
      public String getChildElementXML()
      {
        return null;
      }
    };
    local1.setPacketID(paramString1);
    local1.setTo(paramString2);
    local1.setFrom(paramString3);
    local1.setType(paramType);
    return local1;
  }

  public static FileTransferNegotiator getInstanceFor(Connection paramConnection)
  {
    Object localObject;
    if (paramConnection == null)
      throw new IllegalArgumentException("Connection cannot be null");
    if (!(paramConnection.isConnected()))
      localObject = null;
    while (true)
    {
      while (true)
      {
        return localObject;
        if (!(transferObject.containsKey(paramConnection)))
          break;
        localObject = (FileTransferNegotiator)transferObject.get(paramConnection);
      }
      FileTransferNegotiator localFileTransferNegotiator = new FileTransferNegotiator(paramConnection);
      setServiceEnabled(paramConnection, true);
      transferObject.put(paramConnection, localFileTransferNegotiator);
      localObject = localFileTransferNegotiator;
    }
  }

  private StreamNegotiator getNegotiator(FormField paramFormField)
    throws XMPPException
  {
    label108: Object localObject;
    int i = 0;
    int j = 0;
    Iterator localIterator = paramFormField.getOptions();
    while (true)
    {
      String str;
      do
        while (true)
        {
          if (!(localIterator.hasNext()))
          {
            if ((i != 0) || (j != 0))
              break label108;
            XMPPError localXMPPError = new XMPPError(XMPPError.Condition.bad_request, "No acceptable transfer mechanism");
            throw new XMPPException(localXMPPError.getMessage(), localXMPPError);
          }
          str = ((FormField.Option)localIterator.next()).getValue();
          if ((!(str.equals("http://jabber.org/protocol/bytestreams"))) || (IBB_ONLY))
            break;
          i = 1;
        }
      while (!(str.equals("http://jabber.org/protocol/ibb")));
      j = 1;
    }
    if ((i != 0) && (j != 0) && (paramFormField.getType().equals("list-multi")))
      localObject = new FaultTolerantNegotiator(this.connection, this.byteStreamTransferManager.createNegotiator(), this.inbandTransferManager);
    while (true)
    {
      while (true)
      {
        return localObject;
        if (i == 0)
          break;
        localObject = this.byteStreamTransferManager.createNegotiator();
      }
      localObject = this.inbandTransferManager;
    }
  }

  private StreamNegotiator getOutgoingNegotiator(FormField paramFormField)
    throws XMPPException
  {
    label105: Object localObject;
    int i = 0;
    int j = 0;
    Iterator localIterator = paramFormField.getValues();
    while (true)
    {
      String str;
      do
        while (true)
        {
          if (!(localIterator.hasNext()))
          {
            if ((i != 0) || (j != 0))
              break label105;
            XMPPError localXMPPError = new XMPPError(XMPPError.Condition.bad_request, "No acceptable transfer mechanism");
            throw new XMPPException(localXMPPError.getMessage(), localXMPPError);
          }
          str = (String)localIterator.next();
          if ((!(str.equals("http://jabber.org/protocol/bytestreams"))) || (IBB_ONLY))
            break;
          i = 1;
        }
      while (!(str.equals("http://jabber.org/protocol/ibb")));
      j = 1;
    }
    if ((i != 0) && (j != 0))
      localObject = new FaultTolerantNegotiator(this.connection, this.byteStreamTransferManager.createNegotiator(), this.inbandTransferManager);
    while (true)
    {
      while (true)
      {
        return localObject;
        if (i == 0)
          break;
        localObject = this.byteStreamTransferManager.createNegotiator();
      }
      localObject = this.inbandTransferManager;
    }
  }

  private FormField getStreamMethodField(DataForm paramDataForm)
  {
    FormField localFormField = null;
    Iterator localIterator = paramDataForm.getFields();
    while (true)
    {
      if (!(localIterator.hasNext()));
      do
      {
        return localFormField;
        localFormField = (FormField)localIterator.next();
      }
      while (localFormField.getVariable().equals("stream-method"));
      localFormField = null;
    }
  }

  public static Collection<String> getSupportedProtocols()
  {
    return Collections.unmodifiableList(Arrays.asList(PROTOCOLS));
  }

  public static boolean isServiceEnabled(Connection paramConnection)
  {
    String[] arrayOfString = NAMESPACE;
    int i = arrayOfString.length;
    int j = 0;
    while (true)
    {
      int k;
      if (j >= i)
        k = 1;
      while (true)
      {
        return k;
        String str = arrayOfString[j];
        if (ServiceDiscoveryManager.getInstanceFor(paramConnection).includesFeature(str))
          break;
        k = 0;
      }
      ++j;
    }
  }

  public static void setServiceEnabled(Connection paramConnection, boolean paramBoolean)
  {
    ServiceDiscoveryManager localServiceDiscoveryManager = ServiceDiscoveryManager.getInstanceFor(paramConnection);
    String[] arrayOfString = NAMESPACE;
    int i = arrayOfString.length;
    int j = 0;
    if (j >= i)
      return;
    String str = arrayOfString[j];
    if (paramBoolean)
      localServiceDiscoveryManager.addFeature(str);
    while (true)
    {
      while (true)
        ++j;
      localServiceDiscoveryManager.removeFeature(str);
    }
  }

  public String getNextStreamID()
  {
    StringBuilder localStringBuilder = new StringBuilder();
    localStringBuilder.append("jsi_");
    localStringBuilder.append(Math.abs(randomGenerator.nextLong()));
    return localStringBuilder.toString();
  }

  public StreamNegotiator negotiateOutgoingTransfer(String paramString1, String paramString2, String paramString3, long paramLong, String paramString4, int paramInt)
    throws XMPPException
  {
    StreamNegotiator localStreamNegotiator;
    IQ localIQ;
    StreamInitiation localStreamInitiation = new StreamInitiation();
    localStreamInitiation.setSesssionID(paramString2);
    localStreamInitiation.setMimeType(URLConnection.guessContentTypeFromName(paramString3));
    StreamInitiation.File localFile = new StreamInitiation.File(paramString3, paramLong);
    localFile.setDesc(paramString4);
    localStreamInitiation.setFile(localFile);
    localStreamInitiation.setFeatureNegotiationForm(createDefaultInitiationForm());
    localStreamInitiation.setFrom(this.connection.getUser());
    localStreamInitiation.setTo(paramString1);
    localStreamInitiation.setType(IQ.Type.SET);
    PacketCollector localPacketCollector = this.connection.createPacketCollector(new PacketIDFilter(localStreamInitiation.getPacketID()));
    this.connection.sendPacket(localStreamInitiation);
    Packet localPacket = localPacketCollector.nextResult(paramInt);
    localPacketCollector.cancel();
    if (localPacket instanceof IQ)
    {
      localIQ = (IQ)localPacket;
      if (localIQ.getType().equals(IQ.Type.RESULT))
        localStreamNegotiator = getOutgoingNegotiator(getStreamMethodField(((StreamInitiation)localPacket).getFeatureNegotiationForm()));
    }
    while (true)
    {
      return localStreamNegotiator;
      if (localIQ.getType().equals(IQ.Type.ERROR))
        throw new XMPPException(localIQ.getError());
      throw new XMPPException("File transfer response unreadable");
      localStreamNegotiator = null;
    }
  }

  public void rejectStream(StreamInitiation paramStreamInitiation)
  {
    XMPPError localXMPPError = new XMPPError(XMPPError.Condition.forbidden, "Offer Declined");
    IQ localIQ = createIQ(paramStreamInitiation.getPacketID(), paramStreamInitiation.getFrom(), paramStreamInitiation.getTo(), IQ.Type.ERROR);
    localIQ.setError(localXMPPError);
    this.connection.sendPacket(localIQ);
  }

  public StreamNegotiator selectStreamNegotiator(FileTransferRequest paramFileTransferRequest)
    throws XMPPException
  {
    StreamInitiation localStreamInitiation = paramFileTransferRequest.getStreamInitiation();
    FormField localFormField = getStreamMethodField(localStreamInitiation.getFeatureNegotiationForm());
    if (localFormField == null)
    {
      XMPPError localXMPPError = new XMPPError(XMPPError.Condition.bad_request, "No stream methods contained in packet.");
      IQ localIQ1 = createIQ(localStreamInitiation.getPacketID(), localStreamInitiation.getFrom(), localStreamInitiation.getTo(), IQ.Type.ERROR);
      localIQ1.setError(localXMPPError);
      this.connection.sendPacket(localIQ1);
      throw new XMPPException("No stream methods contained in packet.", localXMPPError);
    }
    try
    {
      StreamNegotiator localStreamNegotiator = getNegotiator(localFormField);
      return localStreamNegotiator;
    }
    catch (XMPPException localXMPPException)
    {
      IQ localIQ2 = createIQ(localStreamInitiation.getPacketID(), localStreamInitiation.getFrom(), localStreamInitiation.getTo(), IQ.Type.ERROR);
      localIQ2.setError(localXMPPException.getXMPPError());
      this.connection.sendPacket(localIQ2);
      throw localXMPPException;
    }
  }
}